先上結果圖片跟測試連結: 線上測試連結
目前要寫一個內部使用的報表系統,維護人員只要寫SQL從DB撈取資料
或是在其他程式邏輯中組成的集合
系統就會自動把集合物件轉成table html的字串
所以寫了一個簡單的table generator
code不長但需要用到JsonNet
跟DataTable
public static string ToHtmlTable(this HashSet<dynamic> obj)
{
return ToHtmlTableConverter(obj);
}
public static string ToHtmlTable(this ICollection obj) {
return ToHtmlTableConverter(obj);
}
public static string ToHtmlTable(this System.Data.DataTable obj)
{
return ConvertDataTableToHTML(obj);
}
private static string ToHtmlTableConverter( object obj )
{
var jsonStr = JsonConvert.SerializeObject(obj);
var data = JsonConvert.DeserializeObject<System.Data.DataTable>(jsonStr);
var html = ConvertDataTableToHTML(data);
return html;
}
private static string ConvertDataTableToHTML(System.Data.DataTable dt)
{
var html = new StringBuilder("<table>");
//表頭
html.Append("<thead><tr>");
for (int i = 0; i < dt.Columns.Count; i++)
html.Append("<th>" + dt.Columns[i].ColumnName + "</th>");
html.Append("</tr></thead>");
//表身
html.Append("<tbody>");
for (int i = 0; i < dt.Rows.Count; i++)
{
html.Append("<tr>");
for (int j = 0; j < dt.Columns.Count; j++)
html.Append("<td>" + dt.Rows[i][j].ToString() + "</td>");
html.Append( "</tr>");
}
html.Append("</tbody>");
html.Append("</table>");
return html.ToString();
}
經過以下實測,支援Array、HashSet、List、不支援Enumerable
var colls1 = collections.ToArray().ToHtmlTable(); //Run Success
var colls2 = collections.ToHashSet().ToHtmlTable();//Run Succes
var colls_list = collections.ToList().ToHtmlTable();//Run Succes
var colls3 = collections.AsEnumerable().ToHtmlTable();//Error doesn't contain defined
因為包含html標籤
所以在cshtml要使用@Html.Raw(生成字串)
來填寫(注意安全性喔!)
直接轉JSON讓前端用JS去轉成Table
效能可以讓使用者來吃下,節省Server負擔
結果圖片跟測試連結: 線上測試連結
View改成:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
var myList = @Html.Raw(ViewBag.Table);
// Builds the HTML Table out of myList.
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) cellValue = "";
row$.append($('<td/>').html(cellValue));
}
$(selector).append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records.
function addAllColumnHeaders(myList, selector) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$(selector).append(headerTr$);
return columnSet;
}
</script>
<body onLoad="buildHtmlTable('#DataTable')">
<table id="DataTable" border="1">
</table>
</body>
以上JS CODE是Manish Mulani大大的:
javascript - Convert json data to a html table - Stack Overflow
以上是粗糙的版本
假如大大們有更好的做法都可以討論、糾正.
我會建議寫成 Helper 讓 View 專心做畫面相關邏輯
public static class HtmlHelper
{
public static HtmlString ToHtmlTable<T>(this IHtmlHelper htmlString, IEnumerable<T> list)
{
string json = JsonConvert.SerializeObject(list);
return htmlString.ToHtmlTable(json);
}
public static HtmlString ToHtmlTable(this IHtmlHelper htmlString, string json)
{
var list = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(json);
if (list == null || !list.Any())
{
throw new Exception("json 字串有誤");
}
var title = list.First().Select(x => x.Key);
var content = list.Select(x => x.Select(y => (y.Value == null) ?
string.Empty : y.Value.ToString()));
string html = convertToHTML(title, content);
return new HtmlString(html);
}
private static string convertToHTML(IEnumerable<string> title, IEnumerable<IEnumerable<string>> content)
{
StringBuilder sb = new StringBuilder();
sb.Append("<table border='1'>");
// 表頭
sb.Append("<thead><tr>");
sb.Append(string.Join(string.Empty, title.Select(x => string.Format("<th>{0}</th>", x))));
sb.Append("</tr></thead>");
// 表身
sb.Append("<tbody>");
foreach (var item in content)
{
sb.Append("<tr>");
sb.Append(string.Join(string.Empty, item.Select(x => string.Format("<td>{0}</td>", x))));
sb.Append("</tr>");
}
sb.Append("</tbody>");
sb.Append("</table>");
return sb.ToString();
}
}
public class TestModel
{
[JsonProperty("姓名")]
public string Name { get; set; }
[JsonProperty("帳號")]
public string Acc { get; set; }
[JsonProperty("密碼")]
public string Pwd { get; set; }
}
public ActionResult Index()
{
var list = Enumerable.Range(0, 15).Select(x => new TestModel
{
Name = string.Format("測試 - {0}", x),
Acc = x.ToString(),
Pwd = Guid.NewGuid().ToString()
});
ViewBag.List = list;
return View();
}
@Html.ToHtmlTable(ViewBag.List as IEnumerable<TestModel>))
大大的模組分離的概念很扎實!
可以額外加一個IHtmlHelper的方法Overload
因為個人報表還有生成html檔案功能
當初只做成一個方法給View跟生成器共同使用
我這樣考量不周全的
謝謝大大